package org.xxx.system.core;

import org.apache.commons.lang3.StringUtils;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.concurrent.ConcurrentHashMap;


/**
 * 请求上下文信息
 */
public class XXXRequestContext extends ConcurrentHashMap {

    protected static Class<? extends XXXRequestContext> contextClass = XXXRequestContext.class;

    protected static final ThreadLocal<? extends XXXRequestContext> threadLocal =
            ThreadLocal.withInitial(() -> {
                try {
                    return (XXXRequestContext) XXXRequestContext.contextClass.newInstance();
                } catch (Throwable t) {
                    throw new RuntimeException(t);
                }
            });

    //不可实列化
    private XXXRequestContext() {
    }

    /**
     * 获取上下文信息
     *
     * @return
     */
    public static XXXRequestContext getCurrentContext() {
        return threadLocal.get();
    }

    /**
     * 添加至上下文
     *
     * @param key
     * @param value
     */
    public void set(String key, Object value) {
        if (value != null) {
            this.put(key, value);
        } else {
            this.remove(key);
        }
    }

    /**
     * 获取当前request
     *
     * @return
     */
    public HttpServletRequest getRequest() {
        return (HttpServletRequest) this.get("request");
    }

    /**
     * 设置当前request
     */
    public void setRequest(HttpServletRequest request) {
        this.put("request", request);
    }

    /**
     * 获取当前response
     *
     * @return
     */
    public HttpServletResponse getResponse() {
        return (HttpServletResponse) this.get("response");
    }

    /**
     * 设置当前response
     *
     * @param response
     */
    public void setResponse(HttpServletResponse response) {
        this.set("response", response);
    }

    /**
     * 获取当前会话cookie信息
     *
     * @param cookieName cookie名称
     * @return
     */
    public String getCookie(String cookieName) {
        HttpServletRequest httpServletRequest = getRequest();
        if (null == httpServletRequest) return null;
        Cookie[] cookies = httpServletRequest.getCookies();
        if (null == cookies) return null;
        for (Cookie cookie : cookies) {
            if (StringUtils.equals(cookie.getName(), cookieName))
                return cookie.getValue();
        }
        return null;
    }

    /**
     * 获取当前会话cookie信息
     *
     * @param cookieName  cookie名称
     * @param cookieValue cookie值
     * @return
     */
    public void setCookie(String cookieName, String cookieValue) {
        HttpServletResponse httpServletResponse = getResponse();
        if (null == httpServletResponse) return;

        httpServletResponse.addCookie(new Cookie(cookieName, cookieValue));
    }

    /**
     * 获取当前会话header信息
     *
     * @param headerName header名称
     * @return
     */
    public String getHeader(String headerName) {
        HttpServletRequest httpServletRequest = getRequest();
        if (null == httpServletRequest) return null;
        return httpServletRequest.getHeader(headerName);
    }

    /**
     * 获取请求跟踪标识
     *
     * @return
     */
    public String getTraceId() {
        String traceId;

        traceId = getHeader("traceId");
        if (null != traceId) return traceId;

        if (null != this.get("traceId")) return this.get("traceId").toString();
        traceId = getCookie("traceId");
        if (null != traceId) return traceId;

        return null;
    }

    /**
     * 设置请求跟踪标识
     *
     * @param traceId
     */
    public void setTraceId(String traceId) {
        if (StringUtils.isBlank(traceId)) return;
        this.put("traceId", traceId);
    }

    /**
     * 获取请求跨度标识
     *
     * @return
     */
    public String getSpanId() {
        return null != this.get("spanId") ? this.get("spanId").toString() : null;
    }

    /**
     * 设置请求跨度标识
     *
     * @param spanId
     */
    public void setSpanId(String spanId) {
        if (StringUtils.isBlank(spanId)) return;
        this.put("spanId", spanId);
    }

    /**
     * 获取请求父级跨度标识
     *
     * @return
     */
    public String getParentSpanId() {
        return null != this.get("parentSpanId") ? this.get("parentSpanId").toString() : null;
    }

    /**
     * 设置请求父级跨度标识
     *
     * @param parentSpanId
     */
    public void setParentSpanId(String parentSpanId) {
        if (StringUtils.isBlank(parentSpanId)) return;
        this.put("parentSpanId", parentSpanId);
    }

    /**
     * 设置会话建立时间
     */
    public void setAcccptTimestamp() {
        this.put("acceptTimestamp", System.currentTimeMillis());
    }

    /**
     * 获取会话建立时间
     *
     * @return
     */
    public long getAcceptTimestamp() {
        return null != this.get("acceptTimestamp") ? Long.parseLong(this.get("acceptTimestamp").toString()) : null;
    }

    /**
     * 获取所有的埋点
     *
     * @return
     */
//    public synchronized List<TracePointWrapper> getTracePoint() {
//        if (this.contains("tracePointWrapperList")) return (List<TracePointWrapper>) this.get("tracePointWrapperList");
//        List<TracePointWrapper> tracePointWrapperList = new ArrayList<>();
//        this.put("tracePointWrapperList", tracePointWrapperList);
//        return tracePointWrapperList;
//    }


    /**
     * 设置请求埋点
     *
     * @param traceKey 埋点键
     * @param traceVal 埋点值
     */
//    public void setTracePoint(String traceKey, String traceVal) {
//        TracePointWrapper tracePointWrapper = new TracePointWrapper(traceKey, traceVal);
//        tracePointWrapper.setTraceId(getTraceId());
//        tracePointWrapper.setParentSpanId(getParentSpanId());
//        tracePointWrapper.setSpanIdId(getSpanId());
//
//        List<TracePointWrapper> tracePointWrapperList = getTracePoint();
//        tracePointWrapperList.add(tracePointWrapper);
//    }

    /**
     * 清空当前会话上下文信息
     */
    public void unset() {
        threadLocal.remove();
    }
}
